package models

import (
	"encoding/json"
	"go-iot/app/iot/core"
	"go-iot/app/iot/ruleengine"
	"go-iot/app/common/logger"
)

const (
	Runing  = "runing"  // 网络状态runing
	Stop    = "stop"    // 网络状态stop
	Stopped = "stopped" // stopped
	Started = "started" // started
)

// 分页结果
type PageResult[T any] struct {
	PageSize    int   `json:"pageSize"`
	PageNum     int   `json:"pageNum"`
	TotalPage   int   `json:"totalPage"`  // 总页数
	TotalCount  int64 `json:"totalCount"` // 总记录数
	FirstPage   bool  `json:"firstPage"`
	LastPage    bool  `json:"lastPage"`
	List        []T   `json:"list"`
	SearchAfter []any `json:"searchAfter"`
}

func PageUtil[T any](count int64, pageNum int, pageSize int, list []T) PageResult[T] {
	tp := int(count) / pageSize
	if int(count)%pageSize > 0 {
		tp = int(count)/pageSize + 1
	}
	return PageResult[T]{
		PageNum:    pageNum,
		PageSize:   pageSize,
		TotalPage:  tp,
		TotalCount: count,
		FirstPage:  pageNum == 1,
		LastPage:   pageNum == tp,
		List:       list,
	}
}

// 分页查询
type PageQuery struct {
	PageNum     int               `json:"pageNum"`
	PageSize    int               `json:"pageSize"`
	Condition   []core.SearchTerm `json:"condition"`
	SearchAfter []any             `json:"searchAfter"`
}

// 得到数据偏移，默认数据从0开始
func (page *PageQuery) PageOffset() int {
	if page.PageNum < 1 {
		page.PageNum = 1
	}
	return (page.PageNum - 1) * page.PageSize
}

// device
type DeviceModel struct {
	Device
	MetaConfig map[string]string `json:"metaconfig,omitempty"`
}

func (d *DeviceModel) FromEnitty(en Device) {
	d.Device = en
	if len(en.MetaConfig) > 0 {
		m := map[string]string{}
		err := json.Unmarshal([]byte(en.MetaConfig), &m)
		if err != nil {
			logger.Errorf(err.Error())
		}
		d.MetaConfig = m
	}
}

func (d *DeviceModel) ToEnitty() Device {
	en := d.Device
	v, err := json.Marshal(d.MetaConfig)
	if err != nil {
		logger.Errorf(err.Error())
	} else {
		en.MetaConfig = string(v)
	}
	return en
}

// product
type ProductModel struct {
	Product
	MetaConfig []core.MetaConfig `json:"metaconfig,omitempty"`
}

func (p *ProductModel) ToProeuctOper() (*core.Product, error) {
	config := map[string]string{}
	for _, v := range p.MetaConfig {
		config[v.Property] = v.Value
	}
	productOpr, err := core.NewProduct(p.Id, config, p.StorePolicy, p.MetaData)
	if productOpr != nil {
		productOpr.NetworkType = p.NetworkType
	}
	return productOpr, err
}

func (d *ProductModel) FromEnitty(en Product) {
	d.Product = en
	if len(en.MetaConfig) > 0 {
		m := []core.MetaConfig{}
		err := json.Unmarshal([]byte(en.MetaConfig), &m)
		if err != nil {
			logger.Errorf(err.Error())
		}
		d.MetaConfig = m
	}
}

func (d *ProductModel) ToEnitty() Product {
	en := d.Product
	v, err := json.Marshal(d.MetaConfig)
	if err != nil {
		logger.Errorf(err.Error())
	} else {
		en.MetaConfig = string(v)
	}
	return en
}

// scene
type RuleModel struct {
	Rule
	DeviceIds []string            `json:"deviceIds"`
	Trigger   ruleengine.Trigger  `json:"trigger"`
	Actions   []ruleengine.Action `json:"actions"`
}

func (d *RuleModel) FromEnitty(en Rule) {
	d.Rule = en
	if len(en.Trigger) > 0 {
		m := ruleengine.Trigger{}
		err := json.Unmarshal([]byte(en.Trigger), &m)
		if err != nil {
			logger.Errorf(err.Error())
		}
		d.Trigger = m
	}
	if len(en.Actions) > 0 {
		m := []ruleengine.Action{}
		err := json.Unmarshal([]byte(en.Actions), &m)
		if err != nil {
			logger.Errorf(err.Error())
		}
		d.Actions = m
	}
}

func (d *RuleModel) ToEnitty() Rule {
	en := d.Rule
	// trigger
	v, err := json.Marshal(d.Trigger)
	if err != nil {
		logger.Errorf(err.Error())
	} else {
		en.Trigger = string(v)
	}
	// actions
	v, err = json.Marshal(d.Actions)
	if err != nil {
		logger.Errorf(err.Error())
	} else {
		en.Actions = string(v)
	}
	return en
}
